#ifndef MESSAGE_H
#define MESSAGE_H

#include <iostream>

#include "Types/AITypes.h"


struct Message
{
	AITypes::EntityID m_sender;
	AITypes::EntityID m_receiver;
	AITypes::MessageType m_message;

	double m_delay;
	
	void* m_extraInfo;

	Message(AITypes::EntityID sender, AITypes::EntityID receiver, AITypes::MessageType message, double delay, void* extraInfo)
		: m_sender(sender)
		, m_receiver(receiver)
		, m_message(message)
		, m_delay(delay)
		, m_extraInfo(extraInfo)
	{
	}

	const char* MessageEnumToString()
	{
		switch (m_message)
		{
		case AITypes::SAMPLE_MESSAGE:
			return "SAMPLE_MESSAGE";
			break;

		case AITypes::INVALID_MESSAGE:
		default:
			return "INVALID_MESSAGE";
			break;
		}
	}
};

inline bool operator==(const Message& lhs, const Message& rhs)
{
	// Messages must have differ by this delay to be unique
	const static double MESSAGE_MIN_DELAY = 0.25;

	return (lhs.m_sender == rhs.m_sender &&
		lhs.m_receiver == rhs.m_receiver &&
		lhs.m_message == rhs.m_message &&
		fabs(lhs.m_delay - rhs.m_delay) < MESSAGE_MIN_DELAY);
}

inline bool operator<(const Message& lhs, const Message& rhs)
{
	if (lhs == rhs)
	{
		return false;
	}

	return lhs.m_delay < rhs.m_delay;
}

inline std::ostream& operator<<(std::ostream& os, const Message& msg)
{
	os << "Time: " << msg.m_delay << " Sender: " << msg.m_sender <<
		" Receiver: " << msg.m_receiver << " Message: " << msg.m_message;

	return os;
}

//handy helper function for dereferencing the ExtraInfo field of the Telegram 
//to the required type.
template <class T>
inline T DereferenceToType(void* p)
{
	return *(T*)(p);
}

#endif